/**
 * 屏幕适配是指设计分辨率与实际移动设备的屏幕分辨率比例不一致，导致移动设备显示黑标
 * 比如说设计分辨率为1280*720，但在2160*1080的设备上必然出现黑边，对于全屏窗口（背景层）的处理是将背景图设计成宽高比为2.0的整图
 * 子节点使用cc.widget组件进行停靠，同时对于需要做屏幕适配的节点则调用App.justNode(cc.Node|cc.Component)接口进行该节点扩宽或者阔高
 * 处理
 * 同时，设计模式必须为高对齐(横屏)或者宽对齐(竖屏)中的一种，绝对不能同时宽高对齐使用，一般情况下表现正常，但是在需要点击拾取节点的
 * 时候触摸坐标和节点包围盒数据错乱，导致拾取异常。
 */

import { App } from "../src/App";
import { EventConst } from "../src/core/EventConst";
import ViewMgr from "../src/core/ViewMgr";

const { ccclass, property } = cc._decorator;

@ccclass
export default class MainScene extends cc.Component {
    @property({ type: cc.Node, tooltip: '游戏操作层' })
    sceneLayout: cc.Node = null;
    @property({ type: cc.Node, tooltip: '加载层' })
    loadLayout: cc.Node = null;
    @property({ type: cc.Node, tooltip: '窗体显示层，屏蔽触碰操作' })
    viewLayout: cc.Node = null;
    @property({ type: cc.Node, tooltip: '遮罩层，屏蔽触碰操作' })
    maskLayout: cc.Node = null;
    @property({ type: cc.Node, tooltip: 'tips层，接受并显示系统等消息' })
    topLayout: cc.Node = null;
    @property({ type: cc.RichText, tooltip: 'tips文本' })
    lblTips: cc.RichText = null;
    @property({ type: cc.Node, tooltip: 'tips节点' })
    tipsNode: cc.Node = null;
    @property({ type: cc.Node, tooltip: '遮罩菊花' })
    imgRound: cc.Node = null;

    private _tipsMsg = [];
    private _msgBoxNode:cc.Node = null;

    onLoad() {
        this.tipsNode.active = false;
        this.maskLayout.active = false;
        this.loadLayout.active = false;
        !cc.sys.isNative && this._lockScene(true,true);
        ViewMgr.init(this.sceneLayout,this.viewLayout,this.topLayout,this.maskLayout);
		cc.game.setFrameRate(30);
        cc.debug.setDisplayStats(false);

        cc.game.on(cc.game.EVENT_HIDE, () => {
            App.Event.emit(EventConst.APP_HIDE);
        });
        cc.game.on(cc.game.EVENT_SHOW, () => {
            App.Event.emit(EventConst.APP_SHOW);
        });
        cc.game.on(cc.game.EVENT_RESTART, () => {
            App.Event.emit(EventConst.APP_RESTART);
        });
    };

    start(){
        App.init('config','lang',(is:boolean)=>{
            this._setView();
            App.Res.loadRes('prefab/view/MessageBox:hall',cc.Prefab,(parefab:cc.Prefab)=>{
                this._msgBoxNode = cc.instantiate(parefab);
                this._msgBoxNode.zIndex = 0;
                this._msgBoxNode.scale = 0;
                this._msgBoxNode.active = true;
                this._msgBoxNode.parent = this.topLayout;
            });
            App.runScene(App.getCfg(`launchScene`),()=>{
                App.Native.callNative('closeLaunch'); // 关闭底层启动图
                this.loadLayout.parent = null; // 已经用不到了，从场景树上卸载
            });
            !cc.sys.isNative && this._lockScene(false,false);
        });
        App.Event.on(EventConst.PUSH_TIPS, this._setTips, this);
        App.Event.on(EventConst.POP_MSG_BOX, this._msgBox, this);
        App.Event.on(EventConst.LOCK_SCREEN, this._lockScene, this);

        // 异常捕获
        const mainVer = parseInt(cc.ENGINE_VERSION.split('.')[0]);
        if (mainVer < 3){
            // @ts-ignore
            window.__errorHandler = (file: any, line: any, errorMessage:any, error: any)=>{
                const exception = {
                    file:file,
                    line:line,
                    errorMessage:errorMessage,
                    error:error
                };
                const exce = JSON.stringify(exception);
                console.log('<=======>', exce);
                if (App.getCfg('debug')){
                    App.MessageBox(App.Util.format(App.getText('comMsgBox'),exce));
                }
            }
        } else {
            const consoleError = window.console.error;
            window.console.error = function(){
                console.log('<=======>', JSON.stringify(arguments));
                consoleError && consoleError.apply(window, arguments);
                if (App.getCfg('debug')){
                    App.MessageBox(App.Util.format(App.getText('comMsgBox'),JSON.stringify(arguments)));
                }
            }
        }
    }

    private _setTips(txt: string) {
        let _setText = (txt: string) => {
            this.lblTips.string = txt;
            this.tipsNode.opacity = 0;
            this.tipsNode.active = true;
            cc.tween(this.tipsNode).stop();
            cc.tween(this.tipsNode).to(0.2,{opacity:255}).delay(3).to(0.2,{opacity:0}).call(()=>{
                if (this._tipsMsg.length < 1) {
                    this.tipsNode.active = false;
                    cc.tween(this.tipsNode).stop();
                } else _setText(this._tipsMsg.shift());
            }).start();
        };

        if (this._tipsMsg.length > 0 && !this._tipsMsg[txt]) {
            this._tipsMsg.push(txt);
            return;
        }

        _setText(txt);
    }

    private _setView(){ 
        cc.debug.setDisplayStats(App.getCfg('debug'));
        const bgCol = App.getCfg('bgColor');
        if (App.Util.isValid(bgCol) && bgCol.length >= 3){
            cc.Camera.main.backgroundColor = cc.color(bgCol[0],bgCol[1],bgCol[2]);
        }
        const fps = App.getCfg('lockFPS') || 30;
        cc.game.setFrameRate(fps);

        
        const size = cc.view.getFrameSize();
        // 实际屏幕比例
        const screenRatio = size.width / size.height;
        const canvas = cc.Canvas.instance;
        // 设计比例
        const design = canvas.designResolution,
        designRatio = design.width / design.height;
        const fit=(isWidth:boolean)=>{
            canvas.fitHeight = !isWidth;
            canvas.fitWidth = isWidth;

            // 这里需要强制将分辨率模式设置为要么高对齐，要么宽对齐
            // 如果是 cc.ResolutionPolicy.SHOW_ALL模式会引起坐标错乱，导致点击拾取节点错误，特别是目标节点经过缩放操作
            // 例如，在斗地主游戏中的扑克墙，如果为cc.ResolutionPolicy.SHOW_ALL将会导致扑克拾取错乱
            cc.view.setResolutionPolicy(canvas.fitHeight ? cc.ResolutionPolicy.FIXED_HEIGHT : cc.ResolutionPolicy.FIXED_WIDTH);
        };
        screenRatio <= 1 ? fit(screenRatio <= designRatio):fit(false);
        App.justNode(this.sceneLayout);
        App.justNode(this.viewLayout);
        App.justNode(this.topLayout);
        App.justNode(this.maskLayout);
    }

    private _msgBox(text: string, call?: (flag: number) => void) {
        this._msgBoxNode.getComponent('MessageBox').showMessage(text,call);
    }

    private _lockScene(flag: boolean, isRound: boolean = false) {
        this.maskLayout.active = flag;
        this.imgRound.active = isRound;
        cc.tween(this.imgRound).stop();
        isRound && cc.tween(this.imgRound).repeatForever(cc.rotateBy(0.1, 35.0)).start();

        // 如果网络正常，等待服务器2秒未响应自动解锁
        if (flag && !isRound) {
            let _id = setTimeout(() => {
                clearTimeout(_id);
                cc.tween(this.imgRound).stop();
                this.maskLayout.active = false;
            }, 5000);
        }
    }
}
